/**
 * @description 滚动列表无限循环自动居中组件
 * @date 2024.9.10
 * @author wz
 * @midify 2024.9.10
 * @editor wz
 */
import { _decorator, CCFloat, EventTouch, math, Rect, tween, Tween, UITransform, v2, v3, Vec2, Vec3 } from 'cc';
import { CRoundScroll } from './CRoundScroll';
import { M_Direction, V_Direction, H_Direction } from '../common/Enum';
const { ccclass, property } = _decorator;
/**
 * @deprecated 思路可以参考，建议使用CVirtualList
 */
@ccclass('CRoundScrollToMid')
export class CRoundScrollToMid extends CRoundScroll {
    @property({ type: CCFloat, tooltip: '额外放大的倍数' })
    scalar: number = 0.5;
    @property({ type: CCFloat, tooltip: '距离中心的距离' })
    distance: number = 180;

    _touchIndex: number = -1;
    _touchStartDate: Date = null;
    _touchStartPos: Vec2 = null;
    _tempSelectIndex: number | null = null;
    _value: number;
    /**
     * 选项的index
     */
    public get value(): number {
        return this._value;
    }

    private getTouchIndex(event: EventTouch) {
        let touchPos = event.getUILocation();//getUILocation 就是UI的世界坐标
        let itemInfoList = this.getValidItemInfo();
        for (let i = 0; i < itemInfoList.length; i++) {
            let itemInfo = itemInfoList[i];
            let uiTrans = itemInfo.node.getComponent(UITransform);
            let localPos = uiTrans.convertToNodeSpaceAR(v3(touchPos.x, touchPos.y));
            let rect = new Rect(-this.itemWidth * itemInfo.node.getScale().x / 2, -this.itemHeight * itemInfo.node.getScale().y / 2, uiTrans.width, uiTrans.height);
            if (rect.contains(v2(localPos.x, localPos.y))) {
                return itemInfo.index
            }
        }
        return -1;
    }


    private onMoveScale() {
        let itemInfoList = this.getValidItemInfo();
        if (itemInfoList.length <= 0) return;

        let min = 0, selItemInfoIndex = 0;
        for (let i = 0; i < itemInfoList.length; i++) {
            let itemInfo = itemInfoList[i];
            let worldPos = this.scroll.getComponent(UITransform).convertToNodeSpaceAR(itemInfo.node.getWorldPosition());
            let ratio = 0;
            if (this.m_direction == M_Direction.HORIZONTAL)
                ratio = this.distance - Math.abs(worldPos.x);
            else if (this.m_direction == M_Direction.VERTICAL)
                ratio = this.distance - Math.abs(worldPos.y);
            if (ratio < 0) ratio = 0;
            let scale = 1 + (ratio / this.distance) * this.scalar;
            itemInfo.node.setScale(Vec3.ONE.clone().multiplyScalar(scale))

            if (this.m_direction == M_Direction.HORIZONTAL) {
                if (i == 0 || Math.abs(worldPos.x) < Math.abs(min)) {
                    min = worldPos.x
                    selItemInfoIndex = i;
                }
            }
            else if (this.m_direction == M_Direction.VERTICAL) {
                if (i == 0 || Math.abs(worldPos.y) < Math.abs(min)) {
                    min = worldPos.y
                    selItemInfoIndex = i;
                }
            }
        }

        for (let i = 0; i < itemInfoList.length; i++) {
            if (selItemInfoIndex == i)
                this._tempSelectIndex = itemInfoList[i].index;
        }
    }

    protected onTouchStart(event: EventTouch) {
        super.onTouchStart(event);
        this._tempSelectIndex = null;
        this._touchStartDate = new Date();
        this._touchStartPos = event.getUILocation();
        this._touchIndex = this.getTouchIndex(event)
    }

    protected onTouchMove(event: EventTouch) {
        super.onTouchMove(event);
        this.onMoveScale();
    }

    protected onTouchEnd(event: EventTouch) {
        super.onTouchEnd(event);

        let deltaTime = new Date().getTime() - this._touchStartDate.getTime();
        let deltaX = Math.abs(event.getUILocation().x - this._touchStartPos.x)
        let touchIndex = this.getTouchIndex(event);
        //双击
        if (this._touchIndex >= 0 && this._touchIndex == touchIndex && deltaTime < 1000 && deltaX < 10)
            this.moveTo(this._touchIndex);
        //滑动
        else if (this._tempSelectIndex != null)
            this.moveTo(this._tempSelectIndex);
        else
            console.log('touchEnd ---- this._tempSelectIndex is null')
    }

    /**
     * 移动到对应的选择
     * @param index 
     * @param isImm 
     * @returns 
     */
    moveTo(index: number, isImm: boolean = false) {
        let length = this._dataList.length;
        let itemInfoList = this.getValidItemInfo();
        if (length <= 0 || itemInfoList.length <= 0) return;

        index = math.clamp(index, 0, length - 1)
        this._value = index;

        let itemInfo = itemInfoList.find(a => a.index == index)

        //没有找到索引(出现在直接调用moveTo和updateData中超出了当前现实的item情况)
        if (itemInfo == null) {
            let unit = 0;
            if (this.m_direction == M_Direction.VERTICAL) {
                unit = this.itemHeight + this.spacingY;
                if (this.v_direction == V_Direction.TOP_TO_BOTTOM)
                    this._scrollOffset = index * unit;
                else if (this.v_direction == V_Direction.BOTTOM_TO_TOP)
                    this._scrollOffset = - index * unit;
            }
            else if (this.m_direction == M_Direction.HORIZONTAL) {
                unit = this.itemWidth + this.spacingX;
                if (this.h_direction == H_Direction.LEFT_TO_RIGHT)
                    this._scrollOffset = -index * unit;
                else if (this.h_direction == H_Direction.RIGHT_TO_LEFT)
                    this._scrollOffset = index * unit;
            }

            itemInfoList.sort((a, b) => a.originIndex - b.originIndex)
            for (let i = 0; i < itemInfoList.length; i++) {
                itemInfoList[i].index = this.isRound ? (index + i) % length : index + i;
            }
            itemInfo = itemInfoList[0];
        }

        const loaclPos = this.scroll.getComponent(UITransform).convertToNodeSpaceAR(itemInfo.node.getWorldPosition());
        let startOffset = this._scrollOffset, endOffset = 0
        if (this.m_direction == M_Direction.HORIZONTAL)
            endOffset = startOffset - loaclPos.x;
        else if (this.m_direction == M_Direction.VERTICAL)
            endOffset = startOffset - loaclPos.y;

        Tween.stopAllByTarget(this.node)
        if (isImm) {
            this._scrollOffset = endOffset
            this.updateItem();
            this.onMoveScale();
            console.log('CRoundScrollToMid-----value:' + this.value)
        }
        else {
            tween(this.node)
                .to(0.2, {}, {
                    onUpdate: (target, ratio: number) => {
                        this._scrollOffset = math.lerp(startOffset, endOffset, ratio)
                        this.updateItem();
                        this.onMoveScale();
                        console.log('CRoundScrollToMid-----value:' + this.value)
                    }
                })
                .start()
        }
    }

    updateData(dataList: any[], index = 0): void {
        super.updateData(dataList);
        this.moveTo(index, true)
    }

}


